﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace iTunesFastForward.Forms
{

    enum WindowShowStyle : uint
    {
        /// <summary>Hides the window and activates another window.</summary>
        /// <remarks>See SW_HIDE</remarks>
        Hide = 0,
        /// <summary>Activates and displays a window. If the window is minimized
        /// or maximized, the system restores it to its original size and
        /// position. An application should specify this flag when displaying
        /// the window for the first time.</summary>
        /// <remarks>See SW_SHOWNORMAL</remarks>
        ShowNormal = 1,
        /// <summary>Activates the window and displays it as a minimized window.</summary>
        /// <remarks>See SW_SHOWMINIMIZED</remarks>
        ShowMinimized = 2,
        /// <summary>Activates the window and displays it as a maximized window.</summary>
        /// <remarks>See SW_SHOWMAXIMIZED</remarks>
        ShowMaximized = 3,
        /// <summary>Maximizes the specified window.</summary>
        /// <remarks>See SW_MAXIMIZE</remarks>
        Maximize = 3,
        /// <summary>Displays a window in its most recent size and position.
        /// This value is similar to "ShowNormal", except the window is not
        /// actived.</summary>
        /// <remarks>See SW_SHOWNOACTIVATE</remarks>
        ShowNormalNoActivate = 4,
        /// <summary>Activates the window and displays it in its current size
        /// and position.</summary>
        /// <remarks>See SW_SHOW</remarks>
        Show = 5,
        /// <summary>Minimizes the specified window and activates the next
        /// top-level window in the Z order.</summary>
        /// <remarks>See SW_MINIMIZE</remarks>
        Minimize = 6,
        /// <summary>Displays the window as a minimized window. This value is
        /// similar to "ShowMinimized", except the window is not activated.</summary>
        /// <remarks>See SW_SHOWMINNOACTIVE</remarks>
        ShowMinNoActivate = 7,
        /// <summary>Displays the window in its current size and position. This
        /// value is similar to "Show", except the window is not activated.</summary>
        /// <remarks>See SW_SHOWNA</remarks>
        ShowNoActivate = 8,
        /// <summary>Activates and displays the window. If the window is
        /// minimized or maximized, the system restores it to its original size
        /// and position. An application should specify this flag when restoring
        /// a minimized window.</summary>
        /// <remarks>See SW_RESTORE</remarks>
        Restore = 9,
        /// <summary>Sets the show state based on the SW_ value specified in the
        /// STARTUPINFO structure passed to the CreateProcess function by the
        /// program that started the application.</summary>
        /// <remarks>See SW_SHOWDEFAULT</remarks>
        ShowDefault = 10,
        /// <summary>Windows 2000/XP: Minimizes a window, even if the thread
        /// that owns the window is hung. This flag should only be used when
        /// minimizing windows from a different thread.</summary>
        /// <remarks>See SW_FORCEMINIMIZE</remarks>
        ForceMinimized = 11
    }

    public partial class ToastForm : Form
    {

        const float OPACITY_INTERVAL = 0.05f;
        const int TIMER_INTERVAL = 40;

        bool _mouseOver = false;

        private const int SW_SHOWNOACTIVATE = 4;
        private const int HWND_TOPMOST = -1;
        private const uint SWP_NOACTIVATE = 0x0010;

        [DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow);

        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        public static extern bool SetWindowPos( 
                int hWnd,           // window handle
                int hWndInsertAfter,    // placement-order handle
                int X,          // horizontal position
                int Y,          // vertical position
                int cx,         // width
                int cy,         // height
                uint uFlags);       // window positioning flags

        public ToastForm()
        {
            InitializeComponent();
            this.Left = Screen.GetWorkingArea(this).Width - this.Width - 2;
            this.Top = Screen.GetWorkingArea(this).Height - this.Height;
            timerUp.Interval = TIMER_INTERVAL;
            timerDown.Interval = TIMER_INTERVAL;
        }

        public string TrackName
        {
            get { return trackNameLabel.Text; }
            set { trackNameLabel.Text = value; }
        }

        public string Artist
        {
            get { return artistLabel.Text; }
            set { artistLabel.Text = value; }
        }

        public string Album 
        {
            get { return albumLabel.Text; }
            set { albumLabel.Text = value; }
        }

        public Image Picture 
        {
            get { return artworkPictureBox.Image; }
            set { artworkPictureBox.Image = value; }
        }

        public int TimeWait 
        {
            get { return (int)timerWait.Interval / 1000; }
            set { timerWait.Interval = value * 1000; }
        }



        public void ShowToast()
        {
            //this.Visible = true;
            //this.BringToFront();

            ShowWindow(Handle, WindowShowStyle.ShowNoActivate);
            SetWindowPos(Handle.ToInt32(), HWND_TOPMOST, Left, Top, Width, Height, SWP_NOACTIVATE);

            timerUp.Enabled = true;
            timerDown.Enabled = false;
            timerWait.Enabled = false;
        }

        private void ToastForm_Click(object sender, EventArgs e)
        {
            HideToastOnClick();
        }

        private void HideToastOnClick()
        {
            if (iTFFSettings.Instance.ToasterHideOnClick)
            {
                // cacher
                timerDown.Enabled = false;
                timerUp.Enabled = false;
                timerWait.Enabled = false;

                this.Opacity = 0;
                ShowWindow(Handle, WindowShowStyle.Hide);
                //this.Visible = false;
            }
        }

        private void timerUp_Tick(object sender, EventArgs e)
        {
            if (this.Opacity < 1)
                this.Opacity += OPACITY_INTERVAL;
            else
            {
                timerUp.Enabled = false;
                if (!_mouseOver)
                    timerWait.Enabled = true;
            }

        }

        private void timerDown_Tick(object sender, EventArgs e)
        {
            if (this.Opacity > 0)
                this.Opacity -= OPACITY_INTERVAL;
            else
            {
                timerDown.Enabled = false;
                ShowWindow(Handle, WindowShowStyle.Hide);
                //this.Visible = false;
            }
        }

        private void timerWait_Tick(object sender, EventArgs e)
        {
            timerWait.Enabled = false;
            timerDown.Enabled = true;
        }

        private void ToastForm_MouseEnter(object sender, EventArgs e)
        {
            if (iTFFSettings.Instance.ToasterReappearOnMouseHOver)
            {
                _mouseOver = true;
                timerUp.Enabled = true;
                timerDown.Enabled = false;
                timerWait.Enabled = false;
            }
        }

        private void ToastForm_MouseLeave(object sender, EventArgs e)
        {
            // TODO tester coordonnées
            if (this.GetChildAtPoint(this.PointToClient(Cursor.Position)) == null)
            {
                _mouseOver = false;
                if (iTFFSettings.Instance.ToasterReappearOnMouseHOver)
                {
                    timerUp.Enabled = false;
                    timerDown.Enabled = true;
                    timerWait.Enabled = false;
                }
            }
        }

    }
}
